﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Configuration;
using System.Web.Script.Serialization;
using Microsoft.ApplicationBlocks.Data;
using EnglishRemix.Services.Model;
using EnglishRemix.Services.Utility;
using Newtonsoft.Json;
using System.Diagnostics;
using EnglishRemix.Services.Model.Requests;
using EnglishRemix.Services.Model.Responses;
using System.Data.SqlClient;
using EnglishRemix.Services.Model.Exceptions;
using AlpineSoft;
using System.Text.RegularExpressions;

namespace EnglishRemix.Services
{
    public class DeviceFacade
    {
        private static string connStr = ConfigurationManager.ConnectionStrings["SqlConStr"].ConnectionString;
        private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public static String privateKeyString = "<RSAKeyValue><Modulus>p8XktVg+8L+90LbWOpdPVFQrMJT39OG11fyYzYP0/y5YjwXCL2vlLzZul7cz9mNUEiVKZk2Rozr8w/OeGRKdgAJ/s5oH1UHY26vxmXP8d0DEDZdfaz9ZYJ+pLfEdxREWSkjTPESMSNyS4GO79EUAXbkgtp0Us/vKENsKkg6kXP0=</Modulus><Exponent>AQAB</Exponent><P>xdqdYAwI7QAtwnjdTaRi9J85O1TRATj8EYr0h2vPlHmfP6McRtEBFmxxEhzWq7z09LoBvYoKQ3NA0EXA3uXmNQ==</P><Q>2RQps1x7f2rvCzFzt0qWFdqg/ENJEZlQ79XAmvInC7Zpdckt3FD3RzE0h3/ETsLKUIKUujSxdw0Aeqvr5r5UqQ==</Q><DP>CS/MbOBCLdb7SPNZuzgtzBP0kVev2LGvqpTcI8mSut8m0MqfDn634TWpzmB+azz71r0oRYe6UEVytfj3KqJcHQ==</DP><DQ>QVQjFJpxhDAfToQMag3lSyBnsGNjewtj4zm15CuZ+plj9ZGc3p/zOxag02JtJrLShhY2Qi+XdNeR3Fke/msrOQ==</DQ><InverseQ>wpY/AhcWgN+yukHV8YChaUPI8p4IEJUfnbgjg9tvkUdmLatZHbwTTYVbhIHqTuVcMzeiJDQKeBIsqpJnAYneNw==</InverseQ><D>JeUyIq/7D4APzNvvia5xsbeNRdzwIPT2kI4MqacbqKP8RtnjIbj6PG7MDiLIbufCrpKTuoXc1oTVYSFe3YTx5AFzU6mYxLZgopMsgLTs1ExI+E+zAqfPHuRKtFbmxieEKt2zjA92JxZ2J8BN0mpcoO3GYmhsgbWliWef5/JUQGE=</D></RSAKeyValue>";
        public static String publicKeyString = "<RSAKeyValue><Modulus>p8XktVg+8L+90LbWOpdPVFQrMJT39OG11fyYzYP0/y5YjwXCL2vlLzZul7cz9mNUEiVKZk2Rozr8w/OeGRKdgAJ/s5oH1UHY26vxmXP8d0DEDZdfaz9ZYJ+pLfEdxREWSkjTPESMSNyS4GO79EUAXbkgtp0Us/vKENsKkg6kXP0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

        public DeviceFacade()
        {
            log.Debug("DeviceFacade initialized");

            
            //String invalidData = "123HelloWorld";
            //String validData = "er-2-0000000";

            //String encryptedData = EncryptData(invalidData);
            //String decryptedData = DecryptData(encryptedData);
            //log.Debug("Data:" + invalidData);
            //log.Debug("Encrypted invalid Data:" + encryptedData);
            //log.Debug("Decrypted Data:" + decryptedData);

            //String validEncryptedData = EncryptData(validData);
            //String validDecryptedData = DecryptData(validEncryptedData);
            //log.Debug("Data:" + invalidData);
            //log.Debug("Encrypted Data:" + validEncryptedData);
            //log.Debug("Decrypted Data:" + validDecryptedData);

            //log.Debug("Done.");
        }

        /*************************************** get Device status *******************************************/

        public Response getDeviceStatus(string deviceId)
        {
            Response response = new Response();
            string sqlStr = "SELECT * FROM Device where Udid = '" + deviceId + "' and Enabled = 1;";
            return response;
        }

        public DeviceActivationResponse ActivateDevice(DeviceActivationRequest actionvationRequest)
        {
            DeviceActivationResponse response = new DeviceActivationResponse();

            String decryptedCode = DecryptData(actionvationRequest.ActivationCode);
            String codePattern = ConfigurationManager.AppSettings["codePattern"];
            Match match = Regex.Match(decryptedCode, codePattern, RegexOptions.IgnoreCase);

            if (!match.Success)
            {
                throw new ServiceException("Invalid activation code.");
            }

            List<SqlParameter> sqlParam = new List<SqlParameter>();
            string sqlStr;
            DataSet dataSet;

            try
            {
                sqlParam.Clear();
                DBUtility.AddSqlParam(sqlParam, "@Udid", SqlDbType.NVarChar, actionvationRequest.DeviceId);
                DBUtility.AddSqlParam(sqlParam, "@Code", SqlDbType.NVarChar, actionvationRequest.ActivationCode);

                // Check to see if this device is already activated.
                sqlStr = "SELECT * FROM Device where Udid = @Udid and Code = @Code;";
                dataSet = DBUtility.ExecuteDataset(sqlStr, sqlParam);
                if (DBUtility.hasResult(dataSet))
                {
                    throw new ServiceException("Device has already been activated.");
                }

                // If the activation code is valid, then ask how many devices have been registered with this particular activation code?
                sqlStr = "SELECT * FROM Device where Code = @Code;";
                dataSet = DBUtility.ExecuteDataset(sqlStr, sqlParam);
                int deviceCount = dataSet.Tables[0].Rows.Count;
                if (deviceCount >= Convert.ToInt32(ConfigurationManager.AppSettings["MaxDevices"]))
                {
                    throw new ServiceException("Maximum number of devices reached.");
                }

                if (addDevice(actionvationRequest)==true)
                {
                    response.Result = true;
                    response.Message = "Device activation successful.";
                }
                else
                {
                    response.Result = false;
                    response.Message = "Device activation failed.";
                }
                return response;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private Boolean addDevice(DeviceActivationRequest actionvationRequest)
        {
            List<SqlParameter> sqlParam = new List<SqlParameter>();
            DBUtility.AddSqlParam(sqlParam, "@Udid", SqlDbType.NVarChar, actionvationRequest.DeviceId);
            DBUtility.AddSqlParam(sqlParam, "@Type", SqlDbType.NVarChar, actionvationRequest.DeviceType);
            DBUtility.AddSqlParam(sqlParam, "@Code", SqlDbType.NVarChar, actionvationRequest.ActivationCode);
            DBUtility.AddSqlParam(sqlParam, "@Enabled", SqlDbType.SmallInt, 1);
            DBUtility.AddSqlParam(sqlParam, "@CreatedOn", SqlDbType.DateTime, DateTime.Now.ToString(ConfigurationManager.AppSettings["DateFormat"]));
            DBUtility.AddSqlParam(sqlParam, "@LastModifiedDate", SqlDbType.DateTime, DateTime.Now.ToString(ConfigurationManager.AppSettings["DateFormat"]));
            DBUtility.AddSqlParam(sqlParam, "@LastModifiedBy", SqlDbType.NVarChar, "System");
            string addDeviceSqlStr = "INSERT INTO Device (Udid, Type, Code, Enabled, CreatedOn, LastModifiedDate, LastModifiedBy) VALUES (@Udid, @Type, @Code, @Enabled, @CreatedOn, @LastModifiedDate, @LastModifiedBy);";

            if (DBUtility.ExecuteNonQuery(addDeviceSqlStr, sqlParam) != 1)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private Boolean validActivationCode(String activationCode)
        {
            return true;
        }

        public static String EncryptData(string data2Encrypt)
        {
            EZRSA rsa;
            rsa = new EZRSA(1024);
            rsa.FromXmlString(publicKeyString);
            byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data2Encrypt);
            byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
            string base64String = Convert.ToBase64String(cipherbytes);
            return HttpUtility.UrlEncode(base64String);
        }

        public static string DecryptData(string data2Decrypt)
        {
            //string urlDecodeData = HttpUtility.UrlDecode(data2Decrypt);
            EZRSA rsa;
            rsa = new EZRSA(1024);
            rsa.FromXmlString(privateKeyString);
            byte[] getpassword = Convert.FromBase64String(data2Decrypt);
            byte[] plain = rsa.Decrypt(getpassword, false);
            return System.Text.Encoding.UTF8.GetString(plain);
        }
    }
}